package com.powernode.listener;

import com.powernode.constant.RabbitMQConstant;
import com.powernode.document.ProductDoc;
import com.powernode.dto.CategoryDto;
import com.powernode.dto.ProductDto;
import com.powernode.feign.PMSFeign;
import com.powernode.service.ProductDocService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
/**
 * 商品的消息队列监听器
 */
@Component
public class ProductMQListener {

    @Autowired
    private ProductDocService service;
    @Autowired
    private PMSFeign PMSFeign;

    /**
     * 新增商品消息监听器--消息的消费端
     * 消息处理成功后手动返回ack，通知队列可以删除消息
     * 消息处理失败后手动返回nack，设置消息是否保存
     * 参数：
     * 1.productDto 消息内容
     * 2.channel 消息通道
     * 3.msg 消息的信息
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitMQConstant.QUEUE_PRODUCT_SAVE),
            exchange = @Exchange(RabbitMQConstant.EXCHANGE_PRODUCT),
            key = RabbitMQConstant.ROUTING_KEY_PRODUCT_SAVE
    ))
    public void saveProductListener(ProductDto productDto, Channel channel, Message msg){

        ProductDoc doc = null;
        try {
            doc = new ProductDoc();
            //将消息赋值到ProductDoc商品文档对象中
            BeanUtils.copyProperties(productDto, doc);

            //根据三级分类id获取三级分类对象
            CategoryDto categoryLevel3 = PMSFeign.getCategoryById(productDto.getCategoryId()).getData();
            //如果三级分类对象不为null
            if (categoryLevel3 != null) {
                //设置商品文档的三级分类id
                doc.setCategoryIdLevel3(categoryLevel3.getId());
                //设置商品文档的三级分类名称
                doc.setCategoryNameLevel3(categoryLevel3.getName());
                //根据三级分类对象的父id获取二级分类
                CategoryDto categoryLevel2 = PMSFeign.getCategoryById(categoryLevel3.getParentId()).getData();
                //如果三级分类对象不为null
                if (categoryLevel2 != null) {
                    //设置商品文档的二级分类名称
                    doc.setCategoryNameLevel2(categoryLevel2.getName());
                    //设置商品文档的二级分类id
                    doc.setCategoryIdLevel2(categoryLevel2.getId());
                    //根据二级分类对象父id获取一级分类对象
                    CategoryDto categoryLevel1 = PMSFeign.getCategoryById(categoryLevel2.getParentId()).getData();
                    //如果一级分类对象不为null
                    if (categoryLevel1 != null){
                        //设置商品文档的一级分类名称和id
                        doc.setCategoryIdLevel1(categoryLevel1.getId());
                        doc.setCategoryNameLevel1(categoryLevel1.getName());
                    }
                }
            }
            //将一条文档信息新增到es库
            service.saveOrUpdate(doc);
            // basicAck()方法，返回ack给消息队列，表示消息处理成功，可以从队列中删除消息
            // 参数，第一个是消息的投递标识，第二个是是否允许处理多条消息
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                // 出现异常时消息处理失败，返回basicNack()
                // 参数第一个是消息的投递标识，第二个是是否允许处理多条消息，第三个是是否将消息重新加入到队列
                channel.basicNack(msg.getMessageProperties().getDeliveryTag(),false,false);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 商品删除消息监听器
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitMQConstant.QUEUE_PRODUCT_DEL),
            exchange = @Exchange(RabbitMQConstant.EXCHANGE_PRODUCT),
            key = RabbitMQConstant.ROUTING_KEY_PRODUCT_DEL
    ))
    public void deleteProductListener(Long productId, Channel channel, Message msg){

        try {
            service.deleteById(productId);
            // 消息处理成功手动返回ack
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                // 消息处理异常返回nack
                channel.basicNack(msg.getMessageProperties().getDeliveryTag(),false,false);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}
